package thingapi

import (
	"errors"
	"fmt"
	"iot-base/common/crudextend"
	"iot-base/common/dbconn"
	"iot-base/common/dbobj"
	"strconv"
	"time"

	"gorm.io/gorm"
)

func EditThing(thing ThingEdit) error {
	if thing.ModelID == "" || thing.Count <= 0 {
		return errors.New("modelid is empty or count is 0")
	}
	now := time.Now()
	var model dbobj.TModel
	model.UID = thing.ModelID
	err := dbconn.DBConnection.Find(&model).Error
	if err != nil {
		return err
	}
	if model.IsStation {
		return errors.New("本接口不能增加站")
	}
	if model.IsEdgeControl {
		thing.IsProxy = true
	}

	name := thing.SName
	if name == "" {
		name = "UNKnown"
	}
	for i := 0; i < thing.Count; i++ {
		var pThing *dbobj.Thing = &thing.Thing

		if i > 0 {
			pThing.SName = name + "#" + strconv.Itoa(i+1)
			pThing.UID = ""
			pThing.AutoID()
		}
		method := "POST"
		ts := dbobj.ThingStation{
			ThingID:   pThing.UID,
			StationID: thing.StationID,
			ModelID:   thing.ModelID,
		}
		msg := crudextend.CrudMsg{
			Action:        method,
			TModelID:      model.UID,
			PThing:        pThing,
			PThingParams:  &thing.Params,
			PThingStation: &ts,
		}
		result := crudextend.GetExtendResult(model.UID, &msg)
		if result != nil {
			if result.Err != nil {
				//webapi.SendError(result.Err.Error(), webapi.DBError, c)
				return result.Err
			}
			if result.PThing != nil {
				pThing = result.PThing
			}
			if result.PThingParams != nil {
				thing.Params = *result.PThingParams
			}
			if result.PThingStation != nil {
				ts = *result.PThingStation
			}

		}
		err := dbconn.DBConnection.Transaction(func(tx *gorm.DB) error {
			var count int64
			tx.Model(pThing).Where("uid=?", pThing.UID).Count(&count)
			if count == 0 {

				err = tx.Create(pThing).Error
			} else {
				err = tx.Save(pThing).Error
			}
			fmt.Println("create thing---------------------------------", *pThing, count, err)

			/*var max int
			err := tx.Raw("select max(sno) from thing_stations where model_id = ? and station_id = ? group by model_id ",
				thing.ModelID, thing.StationID).First(&max).Error
			if err != nil {
				ts.SNO = 0
			} else {
				ts.SNO = max + 1
			}*/
			getTSSNO(&ts)
			ts.ThingID = pThing.UID
			err = tx.Delete(&ts).Error
			if err != nil {
				fmt.Println("error-----delete-----db---------", err, ts)
			}
			err = tx.Create(&ts).Error
			if err != nil {
				fmt.Println("error----------db---------", err, ts)
				return err
			}
			if len(thing.Params) > 0 {
				for _, param := range thing.Params {
					param.ThingID = pThing.UID
					tx.Where("thing_id=? and param_id=?", pThing.UID, param.ParamID).Delete(&dbobj.ThingParam{})
					err = tx.Create(&param).Error
					if err != nil {
						return err
					}
				}

			}
			minfo := dbobj.ThingMaintainInfo{
				ThingID:    pThing.UID,
				CreateTime: &now,
			}
			if pThing.StatusUsed == 1 {
				minfo.UsedTime = &now
			}
			tx.Save(&minfo)
			return nil

		})
		if err != nil {
			//webapi.SendError("tname:"+pThing.SName+" error:"+err.Error(), webapi.DBError, c)
			return errors.New("tname:" + pThing.SName + " error:" + err.Error())
		}

	}
	return nil

}

//ThingCfgInfo 设备或站点的配置信息
type ThingCfgInfo struct {
	PThing          dbobj.Thing `json:"thing"`
	StationID       string
	ParentStationID string
	//PStaion *ThingCfgInfo `json:"station"`
	//PModel  *dbobj.Model `json:"station"`
	Params []dbobj.ThingParam
	No     int
}

type Cfg struct {
	Models []dbobj.TModel  `json:"models"`
	Things []*ThingCfgInfo `json:"things"`
}

//GetThingsAllCfg 获取配置信息
func GetThingsAllCfg() *Cfg {
	var things []dbobj.Thing
	err := dbconn.DBConnection.Model(&dbobj.Thing{}).Find(&things).Error
	var cfg Cfg
	if err == nil {
		var stations []dbobj.Station
		err = dbconn.DBConnection.Model(&dbobj.Station{}).Find(&stations).Error
		if err == nil {
			var thingStations []dbobj.ThingStation
			err = dbconn.DBConnection.Model(&dbobj.ThingStation{}).Find(&thingStations).Error
			if err == nil {
				var thingParams []dbobj.ThingParam
				err = dbconn.DBConnection.Model(&dbobj.ThingParam{}).Find(&thingParams).Error
				if err == nil {
					var models []dbobj.TModel
					var infos []*ThingCfgInfo

					err = dbconn.DBConnection.Model(&dbobj.TModel{}).Find(&models).Error
					if err == nil {
						cfg.Models = models
						mmap := make(map[string]*dbobj.TModel)
						for _, m := range models {
							mmap[m.UID] = &m
						}
						tmap := make(map[string]*ThingCfgInfo)

						for _, thing := range things {
							info := ThingCfgInfo{
								PThing: thing,
							}
							//info.PModel, _ = mmap[thing.ModelID]
							tmap[thing.UID] = &info
							infos = append(infos, &info)
						}
						for _, ts := range thingStations {
							tid := ts.ThingID
							pThing := tmap[tid]
							if pThing != nil {
								pThing.No = ts.SNO
								pThing.StationID = ts.StationID

							}
							//pThing.PStaion, _ = tmap[ts.StationID]
						}
						for _, ss := range stations {
							tid := ss.UID
							pThing := tmap[tid]
							if pThing != nil {
								pThing.ParentStationID = ss.ParentID
							}
						}
						for _, tp := range thingParams {
							tid := tp.ThingID
							pThing := tmap[tid]
							if pThing != nil {
								pThing.Params = append(pThing.Params, tp)
							}
						}

					}
					cfg.Things = infos
					return &cfg
				}
			}
		}
	}
	return nil
}
